package com.jinxin.platform.cdacsrecord.core.utils;

import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Pattern;

/**
 * Description: bccah
 * Created by 34759 on 2019/8/15 14:15
 */
public class DateUtil {
    public static final String COM_CURRENT_DATE_FORMAT;

    static {
        COM_CURRENT_DATE_FORMAT = "yyyy-MM-dd";
    }

    public static final String COM_CURRENT_DATE_HH_FORMAT = "yyyy-MM-dd HH:mm";

    public static final DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    public static final DateFormat df2 = new SimpleDateFormat(COM_CURRENT_DATE_FORMAT);
    public static final DateFormat df3 = new SimpleDateFormat(COM_CURRENT_DATE_HH_FORMAT);
    public static final DateFormat df4 = new SimpleDateFormat("yyyyMMddHHmmss");
    /**
     * 获取前一天的日期
     */
    public static String beforeOneDayToNow() {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, -1);
        return df.format(calendar.getTime());
    }

    public static String getTrace(Throwable t) {

        StringWriter stringWriter = new StringWriter();
        PrintWriter writer = new PrintWriter(stringWriter);
        t.printStackTrace(writer);
        StringBuffer buffer = new StringBuffer();
        buffer.append(stringWriter.getBuffer());
        return buffer.toString();
    }

    public static String getCurrentYMDHMS() {
        return df4.format(new Date());
    }

    public static String getCurrentDayYMD() {

        Calendar seekedDate = Calendar.getInstance();
        seekedDate.setTime(new Date());
        seekedDate.set(Calendar.DAY_OF_MONTH, seekedDate.get(Calendar.DAY_OF_MONTH));

        return df2.format(seekedDate.getTime());
    }

    public static String getSpecifiedDayDate(int field, int daySeek){
        Calendar c = Calendar.getInstance();
        c.setTime(new Date());
        c.add(field, daySeek);
        Date d = c.getTime();
        return df.format(d);
    }

    public static String getYestadyDayYMD() {

        Calendar seekedDate = Calendar.getInstance();
        seekedDate.setTime(new Date());
        seekedDate.set(Calendar.DAY_OF_MONTH, seekedDate.get(Calendar.DAY_OF_MONTH) - 1);

        return df2.format(seekedDate.getTime());
    }

    public static String getCurrentDayYMDHHs() {
        return df3.format(new Date());
    }

    public static Date stringToDate(String dateString) throws ParseException {
        return df3.parse(dateString);
    }

    public static Date stringToDate2(String dateString) throws ParseException {
        return df.parse(dateString);
    }

    public static String formatDate(String date) throws ParseException {
        if (date == null || "".equals(date)) {
            return "";
        }

        String today = getNextNDay(null, 0);
        String befor1day = getNextNDay(null, -1);
        String befor2day = getNextNDay(null, -2);
        String dateS[] = date.split(" ");

        if (dateS[0].equals(befor1day)) {
            return "昨天 " + dateS[1];
        } else if (dateS[0].equals(befor2day)) {
            return "前天 " + dateS[1];
        } else if (dateS[0].equals(today)) {
            return "今天 " + dateS[1].substring(0, 5);
        }

        return dateS[0];
    }

    public static String getNextNDay(int daySeek) {
        Calendar seekedDate = Calendar.getInstance();
        seekedDate.setTime(new Date());
        seekedDate.set(Calendar.DAY_OF_MONTH, seekedDate.get(Calendar.DAY_OF_MONTH) + daySeek);

        return df2.format(seekedDate.getTime()) + " 00:00:00";
    }

    public static String getNextNDay(String dateString, int daySeek) throws ParseException {
        Calendar seekedDate = Calendar.getInstance();
        if (dateString != null && !"".equals(dateString)) {
            seekedDate.setTime(df2.parse(dateString));
        } else {
            seekedDate.setTime(new Date());
        }

        seekedDate.set(Calendar.DAY_OF_MONTH, seekedDate.get(Calendar.DAY_OF_MONTH) + daySeek);

        return df2.format(seekedDate.getTime());
    }

    /**
     * 将日期型转换为指定格式的字符串
     *
     * @param date
     *            日期
     * @param format
     *            格式
     * @return
     */
    public static String dateToString(Date date, String format) {
        if (null == format || "".equals(format)) {
            format = "yyyy年MM月dd日 hh点:mm分:ss秒";
        }
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(date);
    }


    public static String genSecurityKey() {
        UUID uuid = UUID.randomUUID();
        return uuid.toString().replace("-", "");
    }

    public static Date parseStr(String dateStr,String pattern ){
        SimpleDateFormat sim = new SimpleDateFormat(pattern);
        Date date = null;
        try {
            date = sim.parse(dateStr);
        } catch (ParseException e) {
        }
        return date;
    }

    public static String getRandmon() {
        return genSecurityKey();
    }

    public static int div(int v1, int v2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException(
                    "The scale must be a positive integer or zero");
        }

        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);

        return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).intValue();
    }

    public static float divf(int v1, int v2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException(
                    "The scale must be a positive integer or zero");
        }

        if (v1 == 0 || v2 == 0) {
            return 0;
        }

        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);

        return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).floatValue();
    }

    /**
     * 匹配非负整数(正整数 + 0)
     *
     * @param value true:0或正整数 false:负数
     * @return
     */
    private static Pattern nonNgativePattern = Pattern.compile("^[1-9]\\d*|0$");

    public static boolean isNonNegative(Object value) {
        return nonNgativePattern.matcher(String.valueOf(value)).matches();
    }

    /**
     * 匹配正整数
     *
     * @param value true:正整数 false:非正整数
     * @return
     */
    private static Pattern positivePattern = Pattern.compile("^[1-9]\\d*$");

    public static boolean isPositive(Object value) {
        return positivePattern.matcher(String.valueOf(value)).matches();
    }

    /**
     * 验证手机号码
     * 移动号码段:139、138、137、136、135、134、150、151、152、157、158、159、182、183、187、188、147
     * 联通号码段:130、131、132、136、185、186、145
     * 电信号码段:133、153、180、189
     */
    private static Pattern mobilePhonePattern = Pattern.compile("^1(3|4|5|7|8)\\d{9}$");//"^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0,5-9]))\\d{8}$");

    public static boolean isMobilePhone(String value) {
        return mobilePhonePattern.matcher(String.valueOf(value)).matches();
    }

    /**
     * 验证固话号码
     */
    private static Pattern telephonePattern = Pattern.compile("^(0\\d{2}-\\d{8}(-\\d{1,4})?)|(0\\d{3}-\\d{7,8}(-\\d{1,4})?)$");

    public static boolean isTelephone(String value) {
        return telephonePattern.matcher(String.valueOf(value)).matches();
    }

    /*aa=11&bb=22&cc=33*/

    /**
     * 将url参数转换成map
     *
     * @param request 请求
     * @return
     */
    public static HashMap<String, String> getParameterMap(HttpServletRequest request) {
        // 参数Map
        Map properties = request.getParameterMap();
        // 返回值Map
        HashMap returnMap = new HashMap();
        Iterator entries = properties.entrySet().iterator();
        Map.Entry entry;
        String name = "";
        String value = "";
        while (entries.hasNext()) {
            entry = (Map.Entry) entries.next();
            name = (String) entry.getKey();
            Object valueObj = entry.getValue();
            if (null == valueObj) {
                value = "";
            } else if (valueObj instanceof String[]) {
                String[] values = (String[]) valueObj;
                for (int i = 0; i < values.length; i++) {
                    value = values[i] + ",";
                }
                value = value.substring(0, value.length() - 1);
            } else {
                value = valueObj.toString();
            }
            returnMap.put(name, value);
        }
        return returnMap;
    }

    public static String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        System.out.println("x-forwarded-for ip: " + ip + "\n");
        if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
            // 多次反向代理后会有多个ip值，第一个ip才是真实ip
            if (ip.indexOf(",") != -1) {
                ip = ip.split(",")[0];
            }
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
            System.out.println("Proxy-Client-IP ip: " + ip + "\n");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
            System.out.println("WL-Proxy-Client-IP ip: " + ip + "\n");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
            System.out.println("HTTP_CLIENT_IP ip: " + ip + "\n");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            System.out.println("HTTP_X_FORWARDED_FOR ip: " + ip + "\n");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Real-IP");
            System.out.println("X-Real-IP ip: " + ip + "\n");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
            System.out.println("getRemoteAddr ip: " + ip + "\n");
        }
        System.out.println("获取客户端 ip: " + ip + "\n");
        return ip;
    }

    public static String ArrayToXml(HashMap<String, String> arr) {
        String xml = "<xml>";

        Iterator<Map.Entry<String, String>> iter = arr.entrySet().iterator();
        while (iter.hasNext()) {
            Map.Entry<String, String> entry = iter.next();
            String key = entry.getKey();
            String val = entry.getValue();
            if (IsNumeric(val)) {
                xml += "<" + key + ">" + val + "</" + key + ">";

            } else
                xml += "<" + key + "><![CDATA[" + val + "]]></" + key + ">";
        }

        xml += "</xml>";
        return xml;
    }

    public static boolean IsNumeric(String str) {
        if (str.matches("\\d *")) {
            return true;
        } else {
            return false;
        }
    }

    public static String FormatBizQueryParaMap(HashMap<String, String> paraMap,
                                               boolean urlencode) throws Exception {
        // 遍历Map 移除值为空的元素
        Set<Map.Entry<String, String>> set = paraMap.entrySet();
        for (Iterator<Map.Entry<String, String>> it = set.iterator(); it
                .hasNext();) {
            Map.Entry<String, String> entry = (Map.Entry<String, String>) it
                    .next();
            if (StringUtils.isBlank(entry.getValue())) {
                it.remove();
            }
        }
        String buff = "";
        try {
            List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(
                    paraMap.entrySet());

            Collections.sort(infoIds,
                    new Comparator<Map.Entry<String, String>>() {
                        public int compare(Map.Entry<String, String> o1,
                                           Map.Entry<String, String> o2) {
                            return (o1.getKey()).toString().compareTo(
                                    o2.getKey());
                        }
                    });

            for (int i = 0; i < infoIds.size(); i++) {
                Map.Entry<String, String> item = infoIds.get(i);
                // System.out.println(item.getKey());
                if (item.getKey() != "") {

                    String key = item.getKey();
                    String val = item.getValue();
                    if (urlencode) {
                        val = URLEncoder.encode(val, "utf-8");

                    }
                    buff += key + "=" + val + "&";

                }
            }

            if (buff.isEmpty() == false) {
                buff = buff.substring(0, buff.length() - 1);
            }
        } catch (Exception e) {
            throw new Exception(e.getMessage());
        }
        return buff;
    }

    public static String CreateNoncestr() {
        String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        String res = "";
        for (int i = 0; i < 16; i++) {
            Random rd = new Random();
            res += chars.charAt(rd.nextInt(chars.length() - 1));
        }
        return res;
    }

    public static LocalDateTime getDateTimeOfTimestamp(long timestamp) {
        Instant instant = Instant.ofEpochMilli(timestamp);
        ZoneId zone = ZoneId.systemDefault();
        return LocalDateTime.ofInstant(instant, zone);
    }

    public static String transTimeToString(LocalDateTime localDateTime){
        if(localDateTime == null){return "";}
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        return df.format(localDateTime);
    }

    public static long dateDiffMin(String startTime, String endTime) {
        long nm = 1000 * 60;//每分钟毫秒数
        //获得两个时间的毫秒时间差异
        long diff = 0L;
        try {
            Date date1 = stringToDate2(startTime);
            Date date2 = stringToDate2(endTime);
            diff = date2.getTime() - date1.getTime();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return diff / nm;
    }

//    public static void main(String[] args) {
//        System.out.println(dateDiffMin("2021-02-01 00:00:00","2021-02-28 00:00:00"));
//    }

}
